{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 载入数据\n",
    "data = np.genfromtxt(\"kmeans.txt\", delimiter=\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算距离 \n",
    "def euclDistance(vector1, vector2):  \n",
    "    return np.sqrt(sum((vector2 - vector1)**2))\n",
    "  \n",
    "# 初始化质心\n",
    "def initCentroids(data, k):  \n",
    "    numSamples, dim = data.shape\n",
    "    # k个质心，列数跟样本的列数一样\n",
    "    centroids = np.zeros((k, dim))  \n",
    "    # 随机选出k个质心\n",
    "    for i in range(k):  \n",
    "        # 随机选取一个样本的索引\n",
    "        index = int(np.random.uniform(0, numSamples))  \n",
    "        # 作为初始化的质心\n",
    "        centroids[i, :] = data[index, :]  \n",
    "    return centroids  \n",
    "  \n",
    "# 传入数据集和k的值\n",
    "def kmeans(data, k):  \n",
    "    # 计算样本个数\n",
    "    numSamples = data.shape[0]   \n",
    "    # 样本的属性，第一列保存该样本属于哪个簇，第二列保存该样本跟它所属簇的误差\n",
    "    clusterData = np.array(np.zeros((numSamples, 2)))  \n",
    "    # 决定质心是否要改变的变量\n",
    "    clusterChanged = True  \n",
    "  \n",
    "    # 初始化质心  \n",
    "    centroids = initCentroids(data, k)  \n",
    "  \n",
    "    while clusterChanged:  \n",
    "        clusterChanged = False  \n",
    "        # 循环每一个样本 \n",
    "        for i in range(numSamples):  \n",
    "            # 最小距离\n",
    "            minDist  = 100000.0  \n",
    "            # 定义样本所属的簇\n",
    "            minIndex = 0  \n",
    "            # 循环计算每一个质心与该样本的距离\n",
    "            for j in range(k):  \n",
    "                # 循环每一个质心和样本，计算距离\n",
    "                distance = euclDistance(centroids[j, :], data[i, :])  \n",
    "                # 如果计算的距离小于最小距离，则更新最小距离\n",
    "                if distance < minDist:  \n",
    "                    minDist  = distance  \n",
    "                    # 更新样本所属的簇\n",
    "                    minIndex = j  \n",
    "                    # 更新最小距离\n",
    "                    clusterData[i, 1] = distance\n",
    "              \n",
    "            # 如果样本的所属的簇发生了变化\n",
    "            if clusterData[i, 0] != minIndex:  \n",
    "                # 质心要重新计算\n",
    "                clusterChanged = True\n",
    "                # 更新样本的簇\n",
    "                clusterData[i, 0] = minIndex\n",
    "  \n",
    "        # 更新质心\n",
    "        for j in range(k):  \n",
    "            # 获取第j个簇所有的样本所在的索引\n",
    "            cluster_index = np.nonzero(clusterData[:, 0] == j)\n",
    "            # 第j个簇所有的样本点\n",
    "            pointsInCluster = data[cluster_index]  \n",
    "            # 计算质心\n",
    "            centroids[j, :] = np.mean(pointsInCluster, axis = 0) \n",
    "#         showCluster(data, k, centroids, clusterData)\n",
    "  \n",
    "    return centroids, clusterData  \n",
    "  \n",
    "# 显示结果 \n",
    "def showCluster(data, k, centroids, clusterData):  \n",
    "    numSamples, dim = data.shape  \n",
    "    if dim != 2:  \n",
    "        print(\"dimension of your data is not 2!\")  \n",
    "        return 1  \n",
    "  \n",
    "    # 用不同颜色形状来表示各个类别\n",
    "    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']  \n",
    "    if k > len(mark):  \n",
    "        print(\"Your k is too large!\")  \n",
    "        return 1  \n",
    "  \n",
    "    # 画样本点  \n",
    "    for i in range(numSamples):  \n",
    "        markIndex = int(clusterData[i, 0])  \n",
    "        plt.plot(data[i, 0], data[i, 1], mark[markIndex])  \n",
    "  \n",
    "    # 用不同颜色形状来表示各个类别\n",
    "    mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']  \n",
    "    # 画质心点 \n",
    "    for i in range(k):  \n",
    "        plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 20)  \n",
    "  \n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\hokky\\Anaconda3\\lib\\site-packages\\numpy\\core\\fromnumeric.py:3257: RuntimeWarning: Mean of empty slice.\n",
      "  out=out, **kwargs)\n",
      "C:\\Users\\hokky\\Anaconda3\\lib\\site-packages\\numpy\\core\\_methods.py:154: RuntimeWarning: invalid value encountered in true_divide\n",
      "  ret, rcount, out=ret, casting='unsafe', subok=False)\n"
     ]
    }
   ],
   "source": [
    "list_lost = []\n",
    "for k in range(2,10):  # 肘部法则选取k值\n",
    "    min_loss = 10000\n",
    "    min_loss_centroids = np.array([])\n",
    "    min_loss_clusterData = np.array([])\n",
    "    \n",
    "    for i in range(50):\n",
    "        # centroids 簇的中心点 \n",
    "        # cluster Data样本的属性，第一列保存该样本属于哪个簇，第二列保存该样本跟它所属簇的误差\n",
    "        centroids, clusterData = kmeans(data, k)  \n",
    "        loss = sum(clusterData[:,1])/data.shape[0]\n",
    "        if loss < min_loss:  # 选5次代价函数最小的结果\n",
    "            min_loss = loss\n",
    "            min_loss_centroids = centroids\n",
    "            min_loss_clusterData = clusterData\n",
    "    list_lost.append(min_loss)  # 记录很多的loss值，k从2到10\n",
    "    \n",
    "#     print('loss',min_loss)\n",
    "# print('cluster complete!')      \n",
    "# centroids = min_loss_centroids\n",
    "# clusterData = min_loss_clusterData\n",
    "\n",
    "# 显示结果\n",
    "# showCluster(data, k, centroids, clusterData)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2.9811811738953176,\n",
       " 1.9708559728104191,\n",
       " 1.1675654672086735,\n",
       " 1.0712368269135584,\n",
       " 1.0019034362200374,\n",
       " 0.9494848610141549,\n",
       " 0.88831584147126,\n",
       " 0.8301834557030465]"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list_lost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(range(2,10),list_lost)  # 画图，肘部法则取k值\n",
    "plt.xlabel('k')\n",
    "plt.ylabel('loss')  # 画图x轴k值，y轴loss值\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 做预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 做预测\n",
    "\n",
    "x_test = [0,1]\n",
    "np.tile(x_test,(k,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-3.262091  , -1.073162  ],\n",
       "       [-4.589752  ,  2.575316  ],\n",
       "       [ 2.27002871,  4.15117686],\n",
       "       [ 2.46154315, -1.78737555],\n",
       "       [ 4.96163367,  3.81966767],\n",
       "       [-2.46636067,  4.1899698 ],\n",
       "       [-0.704199  ,  1.479481  ],\n",
       "       [-2.28430469, -2.66626685],\n",
       "       [ 3.6872307 ,  3.8429485 ]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 误差\n",
    "np.tile(x_test,(k,1))-centroids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[10.64123769,  1.15167668],\n",
       "       [21.06582342,  6.6322525 ],\n",
       "       [ 5.15303036, 17.2322693 ],\n",
       "       [ 6.05919468,  3.19471136],\n",
       "       [24.61780864, 14.58986108],\n",
       "       [ 6.08293494, 17.55584692],\n",
       "       [ 0.49589623,  2.18886403],\n",
       "       [ 5.21804793,  7.10897889],\n",
       "       [13.59567024, 14.76825317]])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 误差平方\n",
    "(np.tile(x_test,(k,1))-centroids)**2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([11.79291437, 27.69807592, 22.38529966,  9.25390604, 39.20766973,\n",
       "       23.63878186,  2.68476026, 12.32702682, 28.36392341])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 误差平方和\n",
    "((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 最小值所在的索引号\n",
    "np.argmin(((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "def predict(datas):\n",
    "    return np.array([np.argmin(((np.tile(data,(k,1))-centroids)**2).sum(axis=1)) for data in datas])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 画出簇的作用区域"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# ？？？？？？？？？？？？图有问题啊？？？？？？？\n",
    "\n",
    "\n",
    "# 获取数据值所在的范围\n",
    "x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1\n",
    "y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1\n",
    "\n",
    "# 生成网格矩阵\n",
    "xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),\n",
    "                     np.arange(y_min, y_max, 0.02))\n",
    "\n",
    "z = predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似，多维数据转一维。flatten不会改变原始数据，ravel会改变原始数据\n",
    "z = z.reshape(xx.shape)\n",
    "# 等高线图\n",
    "cs = plt.contourf(xx, yy, z)\n",
    "# 显示结果\n",
    "showCluster(data, k, centroids, clusterData)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
